﻿using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using NetTaste;
using server.Models;
using SqlSugar;
using System.Net.Http.Headers;
using System.Security.Policy;
using System.Text;
using TouchSocket.Core;
using TouchSocket.Sockets;
using TcpClient = TouchSocket.Sockets.TcpClient;


namespace BusinessService.Plugin.ProtocolMethod
{
    /// <summary>
    /// 协议基类
    /// </summary>
    public class ProtocolClass
    {
        /// <summary>
        /// 接收数据上下文集合
        /// </summary>
        public static List<ConnectionContext> RevContexts { get; set; } = new List<ConnectionContext>();

        /// <summary>
        /// 发送数据上下文集合
        /// </summary>
        public static List<ConnectionContext> SendContexts { get; set; } = new List<ConnectionContext>();
        #region Socket协议基类
        /// <summary>
        /// 创建TCP客户端
        /// </summary>
        /// <param name="Name">json数据源名称</param>
        /// <param name="IP">IP地址</param>
        /// <param name="Port">端口号</param>
        /// <returns></returns>
        public ConnectionContext CreatTCPClient(string Name, string IP, int Port)
        {
            var tcpClient = new TcpClient();
            tcpClient.Connecting = (client, e) => { return EasyTask.CompletedTask; };//即将连接到服务器，此时已经创建socket，但是还未建立tcp
            tcpClient.Connected = (client, e) => { return EasyTask.CompletedTask; };//成功连接到服务器
            tcpClient.Disconnecting = (client, e) => { return EasyTask.CompletedTask; };//即将从服务器断开连接。此处仅主动断开才有效。
            tcpClient.Disconnected = (client, e) => { return EasyTask.CompletedTask; };//从服务器断开连接，当连接不成功时不会触发。
            tcpClient.Received = (client, e) =>
            {
                //从服务器收到信息。但是一般byteBlock和requestInfo会根据适配器呈现不同的值。
                var msg = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);
                tcpClient.Logger.Info($"客户端接收到信息：{msg}");
                CacheManager.Default.Set_NotExpire($"{client.IP}:{client.Port}", msg);//缓存保留数据


                return EasyTask.CompletedTask;
            };
            //载入配置
            tcpClient.Setup(new TouchSocketConfig()
                .SetRemoteIPHost($"{IP}:{Port}")
                .ConfigureContainer(a =>
                {
                    a.AddConsoleLogger();//添加一个日志注入
                })
                .ConfigurePlugins(a =>
                {
                    a.UseReconnection()
                     .SetTick(TimeSpan.FromSeconds(1))
                     .UsePolling();
                })
                );
            tcpClient.TryConnect();//调用连接，当连接不成功时，会抛出异常。
            //Result result = tcpClient.TryConnect();//或者可以调用TryConnect
            //if (result.IsSuccess())
            //{
            //}
            tcpClient.Logger.Info("客户端成功连接");


            ConnectionContext connectionContext = new ConnectionContext();
            connectionContext.Name = Name;
            connectionContext.Type = "TCP";
            connectionContext.Mode = "客户端";
            connectionContext.Context = tcpClient;
            return connectionContext;
        }

        /// 创建TCP服务器
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public ConnectionContext CreatTCPServer(string Name, string IP, int Port)
        {
            var service = new TcpService();
            service.Connecting = (client, e) => { return EasyTask.CompletedTask; };//有客户端正在连接
            service.Connected = (client, e) =>
            {
                return EasyTask.CompletedTask;
            };//有客户端成功连接
            service.Disconnecting = (client, e) => { return EasyTask.CompletedTask; };//有客户端正在断开连接，只有当主动断开时才有效。
            service.Disconnected = (client, e) => { return EasyTask.CompletedTask; };//有客户端断开连接
            service.Received = (client, e) =>
            {
                //从客户端收到信息
                var msg = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);//注意：数据长度是byteBlock.Len
                client.Logger.Info($"已从{client.Id}接收到信息：{msg}");
                CacheManager.Default.Set_NotExpire($"{client.ServiceIP}:{client.ServicePort}", msg);//缓存保留数据



                // client.Send(mes);//将收到的信息直接返回给发送方
                //client.Send("id",mes);//将收到的信息返回给特定ID的客户端
                //将收到的信息返回给在线的所有客户端。
                //注意：这里只是一个建议思路，实际上群发应该使用生产者消费者模式设计
                //var ids = service.GetIds();
                //foreach (var clientId in ids)
                //{
                //    if (clientId != client.Id)//不给自己发
                //    {
                //        service.Send(clientId, mes);
                //    }
                //}
                return EasyTask.CompletedTask;
            };
            service.Setup(new TouchSocketConfig()//载入配置
                .SetListenIPHosts($"{IP}:{Port}", 7790)//同时监听两个地址
                .ConfigureContainer(a =>//容器的配置顺序应该在最前面
                {
                    a.AddConsoleLogger();//添加一个控制台日志注入（注意：在maui中控制台日志不可用）
                })
                .ConfigurePlugins(a =>
                {
                    //a.Add();//此处可以添加插件
                }));
            service.Start();//启动
            ConnectionContext connectionContext = new ConnectionContext();
            connectionContext.Name = Name;
            connectionContext.Type = "TCP";
            connectionContext.Mode = "服务器";
            connectionContext.Context = service;
            return connectionContext;
        }



        /// <summary>
        /// 客户端向服务器发送消息
        /// </summary>
        /// <param name="tcpClient"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool SocketSend(TcpClient tcpClient, string msg)
        {
            if (tcpClient == null) return false;
            if (tcpClient.CanSend)
            {
                tcpClient.Send(msg);
                return true;
            }
            else
            {
                return false;
            }
        }
        ///
        /// <summary>
        ///服务器向所有在线的客户端发送消息
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public static bool SocketSend(TcpService service, string msg)
        {
            var socketClients = service.GetClients().ToList();
            if (SqlFunc.IsNullOrEmpty(socketClients)) return false;
            foreach (var item in socketClients)
            {
                item.Send(msg);
            }
            return true;
        }
        #endregion
        #region  MQTT协议基类
        /// 创建MQTT连接对象
        /// </summary>
        /// <param name="IP">地址</param>
        /// <param name="Port">端口</param>
        /// <param name="useName">用户名</param>
        /// <param name="passWord">密码</param>
        /// <returns></returns>
        public async  Task< ConnectionContext> CreateMqttObject(string Name, string IP, int Port, string useName, string passWord, string topics)
        {
            try
            {
                // 创建 MQTT 客户端   
                var client = new MqttFactory().CreateMqttClient();

                // 配置 MQTT 客户端选项
                var options = new MqttClientOptionsBuilder()
                    .WithTcpServer(IP, Port) // 指定 MQTT 服务器地址和端口
                    .WithCredentials(useName, passWord)//指定登录验证
                    .Build();

                // 设置消息接收处理程序
                client.UseApplicationMessageReceivedHandler(e =>
                {
                    CacheManager.Default.Set_NotExpire(e.ApplicationMessage.Topic, e.ApplicationMessage.ConvertPayloadToString());//缓存保留数据


                    // 当接收到 MQTT 消息时，将消息内容打印到控制台
                    Console.WriteLine($"接收到的消息: {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}");
                });

             // 连接到 MQTT 服务器
             await   client.ConnectAsync(options);
             // 订阅指定主题的消息
            await    client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topics).Build());
                ConnectionContext connectionContext = new ConnectionContext();
                connectionContext.Name = Name;
                connectionContext.Type = "MQTT";
                connectionContext.Context = client;
                return connectionContext;

            }
            catch (Exception e)
            {
                return null;
            }
        }
        /// <summary>
        /// 发布消息
        /// </summary>
        /// <param name="topic"></param>
        /// <param name="Payload"></param>
        public static void Publish(IMqttClient mqttClient, string topic, string payload)
        {
            Task.Run(async () =>
            {
                // 发布消息
                await mqttClient.PublishAsync(new MqttApplicationMessageBuilder()
                    .WithTopic(topic) // 主题
                    .WithPayload((payload))//"Hello, MQTT ! " + DateTime.Now.ToString("HH :mm :ss"
                    .WithRetainFlag()
                    .Build());
            });
        }




        /// <summary>
        /// MQTT连接成功事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        //public Task MqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg)
        //{
        //    Console.WriteLine($"Mqtt客户端连接成功."); // 这里是随便写的，可以写到自己的日志机制
        //    return Task.CompletedTask;
        //}
        /// <summary>
        /// mqtt断开事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        //public Task MqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg)
        //{
        //    Console.WriteLine($"Mqtt客户端连接断开");// 这里是随便写的，可以写到自己的日志机制
        //    return Task.CompletedTask;
        //}




        /// <summary>
        /// 订阅
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        //private static Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg)
        //{
        //    Console.WriteLine("订阅消息：" + arg.ApplicationMessage.ConvertPayloadToString());
        //    CacheManager.Default.Set_NotExpire(arg.ApplicationMessage.Topic, arg.ApplicationMessage.ConvertPayloadToString());//缓存保留数据


        //    return null;
        //}

        #endregion

        #region HTTP协议基类
        /// <summary>
        /// HTTP发送消息(POST)附加授权验证信息
        /// </summary>
        /// <param name="Url">地址</param>
        /// <param name="model">发送方式</param>
        /// <param name="msg">消息</param>
        /// <param name="tokenString">授权验证信息</param>
        /// <returns></returns>
        public static async Task<string> HttpPostAsync(string Url, string Token, string msg)
        {
            //发送http信息
            using (HttpClient client = new HttpClient())
            {

                if (!Token.IsNullOrEmpty())
                {
                    var tokenString = Token.Split(" ");
                    // 添加Authorization头  
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                      tokenString[0], tokenString[1]);
                }

                var content = new StringContent(msg, Encoding.UTF8, "application/json");
                HttpResponseMessage response = await client.PostAsync(Url, content);
                // 读取响应内容  
                string responseBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine(responseBody);

                return responseBody;
            }
        }
        /// <summary>
        /// HTTP发送消息(Get)附加授权验证信息
        /// </summary>
        /// <param name="Url"></param>
        /// <param name="model"></param>
        /// <param name="msg"></param>
        /// <param name="tokenString"></param>
        /// <returns></returns>
        public static async Task<string> HttpGetAsync(string Url,  string token)
        {

            using (var client = new HttpClient())
            {


                if (!token.IsNullOrEmpty())
                {
                    var tokenString = token.Split(" ");
                    // 添加Authorization头  
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                      tokenString[0], tokenString[1]);
                }
        

                // 发送GET请求  
                HttpResponseMessage response = await client.GetAsync(Url);

                // 读取响应内容  
                string responseBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine(responseBody);

                return responseBody;
            }
        }

        
 







        #endregion

    }

    /// <summary>
    /// 对外连接上下文
    /// </summary>
    public class ConnectionContext
    {
        /// <summary>
        /// 上下文名称
        /// </summary>
        public string Name { get; set; } = string.Empty;

        /// <summary>
        /// 上下文类型
        /// </summary>
        public string Type { get; set; } = string.Empty;


        /// <summary>
        /// 传输模式
        /// </summary>
        public string Mode { get; set; } = string.Empty;


        /// <summary>
        /// 上下文
        /// </summary>
        public dynamic Context { get; set; }

    }



}
